#include "ArchiveWrapper.h"

#include "ValueWithError.h"
#include "Exceptions.h"

ArchiveWrapper::ArchiveWrapper(std::string name, int shotNum, bool write)
{
    m_branchName = std::string("tomson");
//    const char * temp = name.c_str();
    m_handle = OpenArchive(name.c_str(), write );

    if( Valid() )
    {
        if( shotNum < 0 )
            m_shotNum = GetLastShot();
        else
            m_shotNum = shotNum;
    }
}

ArchiveWrapper::~ArchiveWrapper(void)
{
    CloseArchive(m_handle);
}

bool ArchiveWrapper::Valid()
{
    if( m_handle == NULL )
        return false;
    else
        return true;
}

int ArchiveWrapper::FirstShot()
{
    int res = -1;
    if( Valid() )
        res = GetFirstShot();
    
    return res;
}

int ArchiveWrapper::LastShot()
{
    int res = -1;
    if( Valid() )
        res = GetLastShot();
    
    return res;
}

TSignal * ArchiveWrapper::Signal(int chanelNum)
{
	char *signalName = new char[256];
	sprintf(signalName, "chanel%d\0", chanelNum);

	TSignal *signal = GetSignal(signalName, m_branchName.c_str(), m_shotNum);

	delete[] signalName;

	return signal;
}

double ArchiveWrapper::Amplification(int chanelNum)
{
    double res = 1.0;
    
    if( Valid() )
    {
        char *signalName = new char[256];
        sprintf(signalName, "amplification%d\0", chanelNum);

        TSignal *signal = GetSignal(signalName, m_branchName.c_str(), m_shotNum);

        delete[] signalName;

        if(signal != NULL)
            res = (*signal)[0];

    }
    return res;
}

bool ArchiveWrapper::GetCalibrations(CalibData &data)
{
    if( !Valid() )
        return false;

    TString set = GetShotCalibration(m_shotNum);
    if( set.Length() == 0 )
        return false;
    
    const char * setCh = set.Data();
    // fill small calibration params

    TSignal *signal = GetCalibration("Tomson_Radius", setCh);
    if( signal != NULL )
    {
        if( signal->GetSize() > 0 )
            data.smallCalib.radius = (*signal)[0];

        delete signal;
    }

    signal = GetCalibration("Tomson_Tn_Coefficient", setCh);
    if( signal != NULL )
    {
        if( signal->GetSize() >= 5 )
        {
            data.smallCalib.temperatureCoef = (*signal)[0];
            data.smallCalib.densityCoef = (*signal)[1];
            data.smallCalib.energyCoef = (*signal)[2];
            data.smallCalib.angle = (*signal)[3];
            data.smallCalib.distanceAxisLaserRay = (*signal)[4];
        }
    }

    signal = GetCalibration("Tomson_PikesRatios", setCh);
    if( signal != NULL )
    {
        for( size_t i = 0, j = 0; i < std::min(signal->GetSize(), size_t(10)); i+=2, ++j )
            data.peakRatioCalib[j] = ValueWithError( (*signal)[i], (*signal)[i+1] );
    
        delete signal;
    }

    signal = GetCalibration("Tomson_Fons", setCh);
    if( signal != NULL )
    {
        for( size_t i = 0, j = 0; i < std::min(signal->GetSize(), size_t(10)); i+=2, ++j )
            data.bgCalib[j] = ValueWithError( (*signal)[i], (*signal)[i+1] );

        delete signal;
    }

    signal = GetCalibration("Tomson_SpectralCalibration", setCh);
    if( signal != NULL )
    {
        for( size_t i = 0, j = 0; i < std::min(signal->GetSize(), size_t(10)); i+=2, ++j )
        {
            data.spectralCalib.specLine[j] = (*signal)[i];
            data.spectralCalib.specCoef[j] = ValueWithError( (*signal)[i+1], 0 );
        }

        // data.smallCalib.distanceAxisLaserRay = (*signal)[signal->GetSize()-1];
        delete signal;
    }

    signal = GetCalibration("Tomson_Errors", setCh);
    if( signal != NULL )
    {
        for( size_t i = 0; i < std::min(signal->GetSize(), size_t(5)); i+=1 )
            data.spectralCalib.specCoef[i].error = (*signal)[i];

        delete signal;
    }

    return true;
}

void ArchiveWrapper::SaveCalibrations(CalibData &data)
{
    // create new calibration set
    // if there already exists a non-blocked set - replase signals in it
    CreateCalibrationSet();
    
    TSignal *signal = GetCalibration("Tomson_Radius");
    if( signal != NULL )
    {
        signal->SetSize(1);

        signal->SetData(0, data.smallCalib.radius);
        if( ReplaceCalibration("Tomson_Radius", signal) != 0 )
            CalibrationException(std::string("Failed to save calibration. New shots may have been done during saving."));

        delete signal;
    }

    signal = GetCalibration("Tomson_Tn_Coefficient");
    if( signal != NULL )
    {
        signal->SetSize(5);
        signal->SetData(0, data.smallCalib.temperatureCoef);
        signal->SetData(1, data.smallCalib.densityCoef);
        signal->SetData(2, data.smallCalib.energyCoef);
        signal->SetData(3, data.smallCalib.angle);
        signal->SetData(4, data.smallCalib.distanceAxisLaserRay);

        if( ReplaceCalibration("Tomson_Tn_Coefficient", signal) != 0 )
            CalibrationException(std::string("Failed to save calibration. New shots may have been done during saving."));
    }

    signal = GetCalibration("Tomson_PikesRatios");
    if( signal != NULL )
    {
        for( size_t i = 0, j = 0; i < std::min(signal->GetSize(), size_t(10)); i+=2, ++j )
        {
            signal->SetData(i, data.peakRatioCalib[j].val);
            signal->SetData(i+1, data.peakRatioCalib[j].error);
        }

        if( ReplaceCalibration("Tomson_PikesRatios", signal) != 0 )
            CalibrationException(std::string("Failed to save calibration. New shots may have been done during saving."));
        delete signal;
    }

    signal = GetCalibration("Tomson_Fons");
    if( signal != NULL )
    {
        for( size_t i = 0, j = 0; i < std::min(signal->GetSize(), size_t(10)); i+=2, ++j )
        {
            signal->SetData(i, data.bgCalib[j].val);
            signal->SetData(i+1, data.bgCalib[j].error);
        }
        if( ReplaceCalibration("Tomson_Fons", signal) != 0 )
            CalibrationException(std::string("Failed to save calibration. New shots may have been done during saving."));
        delete signal;
    }

    signal = GetCalibration("Tomson_SpectralCalibration");
    if( signal != NULL )
    {
        for( size_t i = 0, j = 0; i < std::min(signal->GetSize(), size_t(10)); i+=2, ++j )
        {
            signal->SetData(i, data.spectralCalib.specLine[j]);
            signal->SetData(i+1, data.spectralCalib.specCoef[j].val);
        }
        if( ReplaceCalibration("Tomson_SpectralCalibration", signal) != 0 )
            CalibrationException(std::string("Failed to save calibration. New shots may have been done during saving."));
        delete signal;
    }

    signal = GetCalibration("Tomson_Errors");
    if( signal != NULL )
    {
        for( size_t i = 0; i < std::min(signal->GetSize(), size_t(5)); i+=1 )
            signal->SetData(i, data.spectralCalib.specCoef[i].error);

        if( ReplaceCalibration("Tomson_Errors", signal) != 0 )
            CalibrationException(std::string("Failed to save calibration. New shots may have been done during saving."));

        delete signal;
    }
}